package com.tt.expandablecalendar.ui.widget.calendar;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;

import android.annotation.SuppressLint;
import android.content.Context;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.LinearLayout;

import com.nineoldandroids.animation.ObjectAnimator;
import com.tt.expandablecalendar.R;
import com.tt.expandablecalendar.ui.widget.calendar.CalendarGridViewAdapter.OnDaySelectListener;

/**
 * 单个月的日历视图 <功能简述> <Br>
 * <功能详细描述> <Br>
 * 
 * @author Kyson http://www.hizhaohui.cn/
 */
@SuppressLint("ClickableViewAccessibility")
public class CalendarCard extends LinearLayout {

    /**
     * 控件的月份或年份改变 <功能简述> <Br>
     * <功能详细描述> <Br>
     * 
     * @author Kyson
     */
    public interface OnCalendarChangeListener {
        void onCalendarChange(YearAndMonth ym);
    }

    /**
     * 年月 <功能简述> </Br> <功能详细描述> </Br>
     * 
     * @author kysonX
     */
    public static class YearAndMonth {
        public int year;
        // as calendar ,month is base 0
        public int month;
    }

    private Context mContext;

    private GridViewWithoutScroll mGv;

    private CalendarGridViewAdapter mGridViewAdapter;

    private YearAndMonth mYearAndMonth = new YearAndMonth();

    private OnCalendarChangeListener mOnCalendarChangeListener;

    public CalendarCard(Context context) {
        super(context);
        this.mContext = context;
        init();
    }

    public CalendarCard(Context context, AttributeSet attrs) {
        super(context, attrs);
        this.mContext = context;
        init();
    }

    /**
     * 初始化日期以及view等控件
     */
    private void init() {
        View view = LayoutInflater.from(mContext).inflate(
                R.layout.widget_common_calendar, this, true);
        mGv = (GridViewWithoutScroll) view
                .findViewById(R.id.widget_common_calendar_gv);
        mGridViewAdapter = new CalendarGridViewAdapter(mContext);
        mGv.setAdapter(mGridViewAdapter);
    }

    /**
     * 设置控件的选中日期 <功能简述>
     * 
     * @param calendar
     */
    public void setCurrentCalendar(Calendar calendar) {
        this.mYearAndMonth.year = calendar.get(Calendar.YEAR);
        this.mYearAndMonth.month = calendar.get(Calendar.MONTH);
        mGridViewAdapter.setSelectedDate(calendar);
        notifyDataChanged();
    }

    /**
     * 设置该控件的当前年月 <功能简述>
     * 
     * @param ym
     */
    public void setCurrentYearAndMonth(YearAndMonth ym) {
        this.mYearAndMonth = ym;
        notifyDataChanged();
    }

    // public void initCurrentCalendar(Calendar calendar) {
    // this.mYearAndMonth.year = calendar.get(Calendar.YEAR);
    // this.mYearAndMonth.month = calendar.get(Calendar.MONTH);
    // notifyDataChanged(calendar.get(Calendar.DAY_OF_MONTH));
    // }

    /**
     * jump to pre month <功能简述>
     */
    public void toBeforeCalendar() {
        if (mYearAndMonth.month <= 0) {
            mYearAndMonth.month = 11;
            mYearAndMonth.year = mYearAndMonth.year - 1;
        } else {
            mYearAndMonth.month = mYearAndMonth.month - 1;
        }
        notifyDataChanged();
    }

    /**
     * jump to next month <功能简述>
     */
    public void toAfterCalendar() {
        if (mYearAndMonth.month >= 11) {
            mYearAndMonth.month = 0;
            mYearAndMonth.year = mYearAndMonth.year + 1;
        } else {
            mYearAndMonth.month = mYearAndMonth.month + 1;
        }
        notifyDataChanged();
    }

    /**
     * 给gridview设置,设置数据 <功能简述>
     * 
     * @param cal
     */
    private List<CalendarItem> getGvDataByYearAndMonth() {
        // 前面的空格数
        int firstDaySpaceCount = getFirstDayOfSpaceCount(mYearAndMonth);
        // 后面的空格数
        int lastDaySpaceCount = getLastDayOfSpaceCount(mYearAndMonth);
        // 获取当前月有多少天
        int dayCount = getDayNumInMonth(mYearAndMonth);

        return getGvListData(firstDaySpaceCount, lastDaySpaceCount, dayCount);
    }

    /**
     * 控件数据变化，通知改变样式 <功能简述>
     */
    private void notifyDataChanged() {
        performAnim();
        mGridViewAdapter.setDatas(getGvDataByYearAndMonth());
        mGridViewAdapter.notifyDataSetChanged();
        if (mOnCalendarChangeListener != null) {
            mOnCalendarChangeListener.onCalendarChange(mYearAndMonth);
        }
    }

    /**
     * perform this view's anim <功能简述>
     */
    private void performAnim() {
        ObjectAnimator.ofFloat(mGv, "alpha", 0f, 1f).setDuration(150).start();
    }

    /**
     * 为gridview中添加需要展示的数据
     * 
     * @param tempSum
     * @param dayNumInMonth
     */
    private List<CalendarItem> getGvListData(int first, int last, int dayCount) {
        List<CalendarItem> list = new ArrayList<CalendarItem>();
        // 当前选中的月份对应的calendar
        Calendar currentCalendar = Calendar.getInstance();
        currentCalendar.set(mYearAndMonth.year, mYearAndMonth.month, 1);

        // 前面的空格，填充
        for (int i = 0; i < first; i++) {
            CalendarItem calendarItem = new CalendarItem();
            Calendar calendar = (Calendar) currentCalendar.clone();
            calendar.add(Calendar.MONTH, -1);
            calendar.set(Calendar.DAY_OF_MONTH, getDayNumInMonth(calendar)
                    - first + i + 1);
            calendarItem.calendar = calendar;
            calendarItem.isToday = isToday(calendar);
            calendarItem.monthPos = CalendarItem.MONTH_PRE;
            list.add(calendarItem);
        }
        // 当前月的日期
        for (int j = 0; j < dayCount; j++) {
            CalendarItem calendarItem = new CalendarItem();
            Calendar calendar = (Calendar) currentCalendar.clone();
            calendar.set(Calendar.DAY_OF_MONTH, j + 1);
            calendarItem.calendar = calendar;
            calendarItem.isToday = isToday(calendar);
            calendarItem.monthPos = CalendarItem.MONTH_CURRENT;
            list.add(calendarItem);
        }

        // 后面的空格填充
        for (int k = 0; k < last; k++) {
            CalendarItem calendarItem = new CalendarItem();
            Calendar calendar = (Calendar) currentCalendar.clone();
            calendar.add(Calendar.MONTH, 1);
            calendar.set(Calendar.DAY_OF_MONTH, k + 1);
            calendarItem.calendar = calendar;
            calendarItem.isToday = isToday(calendar);
            calendarItem.monthPos = CalendarItem.MONTH_NEXT;
            list.add(calendarItem);
        }
        return list;
    }

    public void setOnCalendarChangeListener(
            OnCalendarChangeListener onCalendarChangeListener) {
        this.mOnCalendarChangeListener = onCalendarChangeListener;
    }

    public void setOnDaySelectListener(OnDaySelectListener onDaySelectListener) {
        mGridViewAdapter.setOnDaySelectListener(onDaySelectListener);
    }

    public Calendar getSelectedDate() {
        return mGridViewAdapter.getSelecterDate();
    }

    /**
     * 获取月份第一天前面的空格 <功能简述>
     * 
     * @param cal
     * @return
     */
    private static int getFirstDayOfSpaceCount(YearAndMonth ym) {
        Calendar cal = Calendar.getInstance();
        cal.set(ym.year, ym.month, 1);
        int firstDayInWeek = cal.get(Calendar.DAY_OF_WEEK);
        // 换算为空格数
        return weekToSpaceCount(firstDayInWeek);
    }

    /**
     * 获取月份最后一天后面的空格数 <功能简述>
     * 
     * @param cal
     * @return
     */
    private static int getLastDayOfSpaceCount(YearAndMonth ym) {
        Calendar cal = Calendar.getInstance();
        cal.set(ym.year, ym.month, getDayNumInMonth(ym));
        int lastDayInWeek = cal.get(Calendar.DAY_OF_WEEK);
        return 6 - weekToSpaceCount(lastDayInWeek);
    }

    /**
     * 将周几换算为空格数 <功能简述>
     * 
     * @param week
     * @return
     */
    private static int weekToSpaceCount(int week) {
        return (7 + (week - 2)) % 7;
    }

    /**
     * 获取当前月的总共天数
     * 
     * @param cal
     * @return
     */
    private static int getDayNumInMonth(YearAndMonth ym) {
        Calendar cal = Calendar.getInstance();
        cal.set(Calendar.YEAR, ym.year);
        cal.set(Calendar.MONTH, ym.month);
        return cal.getActualMaximum(Calendar.DATE);
    }

    /**
     * 获取当前月的总共天数
     * 
     * @param cal
     * @return
     */
    private static int getDayNumInMonth(Calendar cal) {
        return cal.getActualMaximum(Calendar.DATE);
    }

    public static boolean isToday(Calendar cal) {
        long now = System.currentTimeMillis();
        int[] nowFields = getTimeFields(now);
        int[] timeFields = getTimeFields(cal.getTimeInMillis());
        return nowFields[0] == timeFields[0] && nowFields[1] == timeFields[1]
                && nowFields[2] == timeFields[2];
    }

    /**
     * 获取时间的每个域 格式：年月日时分秒 <功能简述>
     * 
     * @param time
     * @return
     */
    public static int[] getTimeFields(long time) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTimeInMillis(time);
        int[] timeFields = new int[6];
        timeFields[0] = calendar.get(Calendar.YEAR);
        timeFields[1] = calendar.get(Calendar.MONTH);
        timeFields[2] = calendar.get(Calendar.DAY_OF_MONTH);
        timeFields[3] = calendar.get(Calendar.HOUR_OF_DAY);
        timeFields[4] = calendar.get(Calendar.MINUTE);
        timeFields[5] = calendar.get(Calendar.SECOND);
        return timeFields;
    }
}
